package com.syjy.tunnelworker.gathers.iml;


import com.syjy.DataExchangeException;
import com.syjy.tunnelinfo.DataPoint;
import com.syjy.tunnelinfo.TunnelStatus;
import com.syjy.tunnelinfo.gathertunnelinfo.Gather104TcpTunnelInfo;
import com.syjy.tunnelworker.BaseProtocolTunnel;
import com.syjy.tunnelworker.gathers.DataGatherInterface;
import com.syjy.tunnelworker.workassist.SingleThreadPoolExecutorUtil;
import wei.yigulu.iec104.nettyconfig.Iec104HSMasterBuilder;
import wei.yigulu.iec104.util.SendDataFrameHelper;


import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 104协议数据获取
 *
 * @author 修唯xiuwei
 * @version 3.0
 */
public class Iec104TcpDataGather extends BaseProtocolTunnel<Gather104TcpTunnelInfo,Iec104HSMasterBuilder> implements DataGatherInterface {

	

	/**
	 * 点表
	 */
	private Map<Integer, DataPoint> iec104DataPoint = new HashMap<>();


	/**
	 * iec104tcp数据采集
	 * 构造方法
	 *
	 * @param gather104TcpTunnelInfo 104采集通道信息
	 * @throws DataExchangeException 数据交换异常
	 */
	public Iec104TcpDataGather(Gather104TcpTunnelInfo gather104TcpTunnelInfo) throws DataExchangeException {
		super(gather104TcpTunnelInfo);
		parseGatherDataPoint();
	}

	@Override
	public void parseGatherDataPoint() throws DataExchangeException {
		List<DataPoint> dataPoints = this.getTunnelInfo().getDataPoints();
		iec104DataPoint = new HashMap<>();
		if (dataPoints == null || dataPoints.size() == 0) {
			return;
		}
		for (DataPoint d : dataPoints) {
			this.iec104DataPoint.put(d.getProtocolPoint(), d);
		}
		if (protocolBuilder != null) {
			protocolBuilder.getConfigInfoMap().put("104DataPoint", this.iec104DataPoint);
		}
	}


	@Override
	public Iec104TcpDataGather buildTunnel() throws DataExchangeException {
		protocolBuilder = new MyMasterBuilder(tunnelInfo.getRemoteIp(), tunnelInfo.getRemotePort());
		protocolBuilder.getConfigInfoMap().put("104DataPoint", this.iec104DataPoint);
		protocolBuilder.setLog(log);
		if (getTunnelInfo().getRemoteSpareIp() != null) {
			protocolBuilder.setSpareIp(getTunnelInfo().getRemoteSpareIp());
		}
		if (getTunnelInfo().getRemoteSparePort() != null) {
			protocolBuilder.setSparePort(getTunnelInfo().getRemoteSparePort());
		}
		if (getTunnelInfo().getSelfIp() != null) {
			protocolBuilder.setSelfIp(getTunnelInfo().getSelfIp());
		}
		if (getTunnelInfo().getSelfPort() != null) {
			protocolBuilder.setSelfPort(getTunnelInfo().getSelfPort());
		}
		getProtocolTunnelContainer().addTunnel(this);
		this.setTunnelStatus(TunnelStatus.BUILT);
		parseGatherDataPoint();
		log.info("成功创建Iec 104Tcp master通道对象：{}", this.tunnelInfo.getTunnelName());
		return this;
	}

	@Override
	public Iec104TcpDataGather startTunnel() throws DataExchangeException {
		protocolTunnelContainer.addUpdateDateTask(this);
		try {
			SingleThreadPoolExecutorUtil.executeBySingleThreadExecutor(() -> this.protocolBuilder.create());
		} catch (Exception e) {
			new DataExchangeException(10009, "104master通道创建时发生异常");
		}
		log.info("IEC104 TCP master {} 通道开始连接", getTunnelInfo().getTunnelName());
		return this;
	}


	@Override
	public BaseProtocolTunnel tunnelStop() throws DataExchangeException {
		if (this.protocolBuilder != null) {
			this.protocolBuilder.stop();
		}
		log.info("104 master {} 关闭", tunnelInfo.getTunnelName());
		return super.tunnelStop();
	}

	@Override
	public void getDataFromProtocol() throws DataExchangeException {
		log.info("向104 通道:{} 中发送总召唤", getTunnelInfo().getTunnelName());
		try {
			if (this.protocolBuilder.getFuture().channel() != null && this.protocolBuilder.getFuture().channel().isActive()) {
				SendDataFrameHelper.sendTotalSummonFrame(this.protocolBuilder.getFuture().channel(), getTunnelInfo().getPublicAddress(), 6, this.log);
			}
		} catch (Exception e) {
			log.error("104通道发送数据时发生异常", e);
			throw new DataExchangeException(10008, "104通道发送数据时发生异常");
		}
	}


	/**
	 * 内部类 用于设置连接 和断连 的后续动作
	 */
	class MyMasterBuilder extends Iec104HSMasterBuilder {
		public MyMasterBuilder(String ip, Integer port) {
			super(ip, port);
		}


		@Override
		public void connected() {
			log.info("IEC104 Master {}连接成功", getTunnelInfo().getTunnelName());
			setTunnelStatus(TunnelStatus.CONNECTED);
		}

		@Override
		public void disconnected() {
			log.error("IEC104 Master {}断开连接", getTunnelInfo().getTunnelName());
			setTunnelStatus(TunnelStatus.LOSECONN);
		}


	}

}
